package com.atguigu.srb.oss.service.impl;

import com.atguigu.common.exception.Assert;
import com.atguigu.common.exception.BusinessException;
import com.atguigu.common.result.ResponseEnum;
import com.atguigu.srb.oss.service.FileService;
import com.atguigu.srb.oss.util.OssProperties;
import io.minio.*;
import io.minio.http.Method;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.DateTime;
import org.springframework.stereotype.Service;

import java.io.InputStream;
import java.util.UUID;

@Service
@Slf4j
public class FileServiceImpl implements FileService {

    /**
     * 上传文件
     */
    @Override
    public String uploadFile(InputStream inputStream, String module, String fileName) {
        //获取MinioClient对象
        MinioClient minioClient = getMinioClient();
        Assert.isNotNull(minioClient, ResponseEnum.UPLOAD_ERROR);

        //判断存储桶是否创建，无则创建存储桶。创建失败则抛出"文件上传"异常
        Assert.isTrue(makeBucket(minioClient, OssProperties.BUCKET_NAME), ResponseEnum.UPLOAD_ERROR);

        try {
            //构建日期路径
            String folder = new DateTime().toString("yyyy/MM/dd");

            //文件名:uuid.扩展名
            fileName = fileName.substring(0, fileName.lastIndexOf(".")) + "-"
                    + UUID.randomUUID().toString() + fileName.substring(fileName.lastIndexOf("."));
            //文件根路径
            String objectPath = module + "/" + folder + "/" + fileName;

            //文件上传至minio
            minioClient.putObject(
                    PutObjectArgs.builder()
                            .bucket(OssProperties.BUCKET_NAME)
                            .object(objectPath)
                            .stream(inputStream, -1, 10485760)
                            .build());
            log.info("{}文件上传至minio成功", objectPath);

            return getRreviewFileUrl(minioClient, objectPath);
        } catch (Exception e) {
            log.error("文件上传失败");
            e.printStackTrace();
            throw new BusinessException(ResponseEnum.UPLOAD_ERROR);
        }
    }

    @Override
    public void removeFile(String url) {
        //获取MinioClient对象
        MinioClient minioClient = getMinioClient();
        Assert.isNotNull(minioClient, ResponseEnum.UPLOAD_ERROR);

        String host = OssProperties.ENDPOINT + "/" + OssProperties.BUCKET_NAME + "/";
        String objectPath = url.substring(host.length(),url.lastIndexOf("?"));
        try{
            minioClient.removeObject(RemoveObjectArgs.builder()
                    .bucket(OssProperties.BUCKET_NAME)
                    .object(objectPath).build());
            log.info("删除文件{}成功",objectPath);
        }catch (Exception e){
            log.error("删除文件失败");
            throw new BusinessException(ResponseEnum.ERROR);
        }
    }

    public MinioClient getMinioClient() {
        try {
            return MinioClient.builder()
                    .endpoint(OssProperties.ENDPOINT)
                    .credentials(OssProperties.ACCESS_KEY, OssProperties.SECRET_KEY)
                    .build();
        } catch (Exception e) {
            log.error("创建MinioClient对象失败");
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 判断存储桶是否存在
     */
    public boolean bucketsExist(MinioClient minioClient, String bucketName) {
        boolean flag = false;
        try {
            flag = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
            if (flag) {
                return true;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return false;
    }

    /**
     * 判断存储桶是否创建并且创建存储桶
     */
    public boolean makeBucket(MinioClient minioClient, String bucketName) {
        try {
            boolean flag = bucketsExist(minioClient, bucketName);
            if (!flag) {
                log.info("{}存储桶不存在，开始创建存储桶");
                minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
                log.info("存储桶创建完成");
            }
            return true;
        } catch (Exception e) {
            log.error("{}存储桶创建失败", bucketName);
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 根据文件路径得到预览文件的绝对路径
     */
    public String getRreviewFileUrl(MinioClient minioClient, String fileName) {
        try {
            return minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs
                    .builder()
                    .bucket(OssProperties.BUCKET_NAME)
                    .object(fileName)
                    .method(Method.GET)
                    .build());
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}
